#include "snipmath.h"
#include <math.h>
#include <stdio.h>

#define LOCKED 1
#define FREEEE 0
#define GLOBALOCUPADO 1
#define N 3

#define ADDR_LOCK 5242880

//VARIAVEIS GLOBAIS TEM ENDEREÇO COMPARTILHADO PELOS CORES
//VARIAVEIS LOCAIS SÂO INDEPENDETES

int AcquireGlobalLock() ;
void ReleaseGlobalLock();
int AcquireLock(int );
void ReleaseLock(int);

int global_locks[N]; // VETOR DE LOCKS LOCAIS - CADA [] RECEBE O NUMERO DO CORE RESPONSAVEL
int global_proc = 1; // CONTADOR GLOBAL DOS PROCESSADORES, CADA UM RECEBE UM NUMERO UNICO

/* The printf's may be removed to isolate just the math calculations */

int main(void)
{
  int proc = 0;
  while(AcquireGlobalLock() != 0);
  proc = global_proc++;
  AcquireLock(proc);
  ReleaseGlobalLock();

  if(global_locks[1] == proc){ 

    int j;
    unsigned long l = 0x3fed0169L;
    struct int_sqrt q;
    FILE *square_sol = fopen("square_sol.txt", "w");

    printf("********* INTEGER SQR ROOTS ***********\n");
    /* perform some integer square roots */
    for (j = 0; j < 1001; ++j)
      {
        usqrt(j, &q);
	fprintf(square_sol, "sqrt(%3d) = %2d\n",
		j, q.sqrt);
      }
    usqrt(l, &q);
    fprintf(square_sol, "\nsqrt(%lX) = %X\n", l, q.sqrt);
    fflush(square_sol);
    fclose(square_sol);
  }

  if(global_locks[0] == proc) {
    double X;
    FILE *rad2grad_sol = fopen("rad2grad_sol.txt", "w");

    printf("********* ANGLE CONVERSION ***********\n");
    /* convert some rads to degrees */
    for (X = 0.0; X <= 360.0; X = d2_add(X, 1.0))
      fprintf(rad2grad_sol,"%3.0f degrees = %.12f radians\n", X, deg2rad(X));
    puts("");
    for (X = 0.0; X <= (2 * PI + 1e-6); X = d2_add(X, (PI / 180)))
      fprintf(rad2grad_sol,"%.12f radians = %3.0f degrees\n", X, rad2deg(X));
    fflush(rad2grad_sol);
    fclose(rad2grad_sol);
  }

  if(global_locks[2] == proc){
    double  a1 = 1.0, b1 = -10.5, c1 = 32.0, d1 = -30.0;
    double  a2 = 1.0, b2 = -4.5, c2 = 17.0, d2 = -30.0;
    double  a3 = 1.0, b3 = -3.5, c3 = 22.0, d3 = -31.0;
    double  a4 = 1.0, b4 = -13.7, c4 = 1.0, d4 = -35.0;
    double  x[3];
    
    int solutions;
    int i;
    FILE *cubic_sol = fopen("cubic_sol.txt", "w");

    /* solve soem cubic functions */
    printf("********* CUBIC FUNCTIONS ***********\n");

    /* should get 3 solutions: 2, 6 & 2.5   */
    SolveCubic(a1, b1, c1, d1, &solutions, x);  
    fprintf(cubic_sol, "Solutions:");
    for(i=0;i<solutions;i++) {
      fprintf(cubic_sol, " %f",x[i]);
//      printf(" %lf", x[i]);
    }
    fprintf(cubic_sol, "\n");
//    printf("\n");

    /* should get 1 solution: 2.5           */
    SolveCubic(a2, b2, c2, d2, &solutions, x);  
    fprintf(cubic_sol, "Solutions:");
    for(i=0;i<solutions;i++) {
      fprintf(cubic_sol, " %f",x[i]);
//      printf(" %lf", x[i]);
    }
    fprintf(cubic_sol, "\n");
//    printf("\n");

    SolveCubic(a3, b3, c3, d3, &solutions, x);
    fprintf(cubic_sol, "Solutions:");
    for(i=0;i<solutions;i++) {
      fprintf(cubic_sol, " %f",x[i]);
//      printf(" %lf", x[i]);
    }
    fprintf(cubic_sol, "\n");
//    printf("\n");

    SolveCubic(a4, b4, c4, d4, &solutions, x);
    fprintf(cubic_sol, "Solutions:");
    for(i=0;i<solutions;i++) {
      fprintf(cubic_sol, " %f",x[i]);
//      printf(" %lf", x[i]);
    }
    fprintf(cubic_sol, "\n");
//    printf("\n");

    /* Now solve some random equations */
    for(a1=1;a1<10;a1=d1_add(a1, 1.0)) {
      for(b1=10;b1>0;b1--) {
        for(c1=5;c1<15;c1=d1_add(c1, 0.5)) {
          for(d1=-1;d1>-11;d1--) {
            SolveCubic(a1, b1, c1, d1, &solutions, x);  
            fprintf(cubic_sol, "Solutions:");
            for(i=0;i<solutions;i++) {
              fprintf(cubic_sol, " %f",x[i]);
//	      printf(" %lf", x[i]);
	    }
            fprintf(cubic_sol, "\n");
//	    printf("\n");
          }
        }
      }
    }
    fflush(cubic_sol);
    fclose(cubic_sol);
  }

  exit(0);
  return 0;
}

int AcquireGlobalLock() {
  volatile int *lock = (int *) ADDR_LOCK;
  int ret;
  ret = *lock;
  return ret; 
}

void ReleaseGlobalLock() {
  volatile int *lock = (int *) ADDR_LOCK;
  *lock = FREEEE;
} 

int AcquireLock(int proc) {
  int i;
  for(i = 0; i < N; i++){
    if(global_locks[i] == FREEEE){
      global_locks[i] = proc;
      break;
    }
  }
}

void ReleaseLock(int lock) {
  global_locks[lock] = FREEEE;
  return;
}
